package modularity.passiveDrift;

import java.util.Properties;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import ec.util.MersenneTwisterFast;


/**
 * List of operations performed.
 * 
 * 1 - removing of a randomly chosen connection
 * 2 - adding a connection between two previously unconnected nodes.
 * 3 - adding a new node by splitting a connection
 * 
 * @author Fernando
 *
 */
public class BasicMutatorManager implements MutationManager {

	protected double removeConnectionProb;
	protected double addConnectionProb;
	protected double addNodeProb;
	protected int mutationThreads;

	public BasicMutatorManager(Properties arguments){

		//get the value or, if not found, set a default value.
		removeConnectionProb = Double.valueOf(arguments.getProperty("remove-connection", "0.2"));
		addConnectionProb = Double.valueOf(arguments.getProperty("add-connection", "0.2"));
		addNodeProb = Double.valueOf(arguments.getProperty("add-node", "0.1"));
	}

	public void mutate(ListedPopulation pop) throws InterruptedException{
		int populationsize = pop.size();
		ExecutorService eservice = Executors.newFixedThreadPool(mutationThreads);
		CompletionService<Object> cservice = new ExecutorCompletionService<Object>(eservice);

		for(int i = 0; i < populationsize; i++){
			cservice.submit(new MutationTask(pop.get(i), i, new BasicMutator(removeConnectionProb, addConnectionProb, addNodeProb), new MersenneTwisterFast()));
		}

		eservice.shutdown();
		
		for(int index = 0; index < populationsize; index++) {
			Object result;
			try {
				result = cservice.take().get();
			} catch (InterruptedException e) {
	            // Something went wrong with a task submitted
	            System.out.println("Error Interrupted exception");
	            e.printStackTrace();
	            System.exit(0);
	        } catch (ExecutionException e) {
	            // Something went wrong with the result
	            e.printStackTrace();
	            System.out.println("Error get() threw exception");
	            System.exit(0);
	        }
		}
		
	}

	public void setMutationThreads(int threads){
		this.mutationThreads = threads;
	}

	public double getRemoveConnectionProb() {
		return this.removeConnectionProb;
	}

	public double getAddConnectionProb() {
		return this.addConnectionProb;
	}

	public double getAddNodeProb() {
		return this.addNodeProb;
	}
}
